package com.cloudkinto.service.event.order;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.cloudkinto.common.RabbitQueueConstant;
import com.cloudkinto.entity.OrderBoxProductDo;
import com.cloudkinto.entity.ProductDo;
import com.cloudkinto.service.consumer.vo.order.PlatOrderSendConsumerReq;
import com.cloudkinto.service.order.allocate.AllocatePlanService;
import com.cloudkinto.service.order.input.OrderInputService;
import com.cloudkinto.service.order.outbound.OrderOutboundPackageDetailService;
import com.cloudkinto.service.order.outbound.OrderOutboundPackageService;
import com.cloudkinto.service.order.outbound.OutboundService;
import com.cloudkinto.service.order.shelf.OrderInputShelfService;
import com.cloudkinto.service.product.ProductService;
import com.cloudkinto.service.wr.QuotationSchemeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author long
 * @Description 订单事件监听
 * @Date 2025/2/10 13:18
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class OrderEventListener {

    private final QuotationSchemeService quotationSchemeService;
    private final OutboundService outboundService;
    private final OrderInputShelfService shelfService;
    private final ProductService productService;
    private final OrderOutboundPackageService outboundPackageService;
    private final OrderOutboundPackageDetailService outboundPackageDetailService;
    private final AllocatePlanService allocatePlanService;
    private final RabbitTemplate rabbitTemplate;
    private final OrderInputService orderInputService;

    /**
     * 出库单 出库后 平台订单出库
     *
     * @param event 事件实体
     */
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void platformOrderSendEvent(PlatformOrderSendEvent event) {
//        log.error("Ec出库获取单号后 ex平台出库：" + event.getList().size());
        for (PlatOrderSendConsumerReq req : event.getList()) {
            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformOrder_Finish, JSON.toJSONString(req));
        }

    }


    /**
     * 入库单上架后事务提交后执行事件添加计费
     *
     * @param event 事件实体
     */
    @Async("threadPoolExecutor")
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void inboundAddCostEvent(InboundAddCostEvent event) {
        quotationSchemeService.costAddInput(shelfService.buildInboundCostReq(event.getInputDo(), event.getStatus()));
    }

    /**
     * wms入库单推送到筋斗云入库单
     *
     * @param event 事件实体
     */
    @Async("threadPoolExecutor")
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void proxyWarehousePushToJdy(PostJdyInputOrderEvent event) {
        Map<String, List<OrderBoxProductDo>> boxMarkNoMatchList = event.getBoxProductList().stream().filter(item -> StrUtil.isNotBlank(item.getBoxMarkNumber())).collect(Collectors.groupingBy(OrderBoxProductDo::getBoxMarkNumber));
        Map<String, List<OrderBoxProductDo>> boxTypeNoMatchList = event.getBoxProductList().stream().filter(item -> StrUtil.isNotBlank(item.getBoxTypeNumber())).collect(Collectors.groupingBy(OrderBoxProductDo::getBoxTypeNumber));
        //产品id列表
        Set<Long> productIdSet = new HashSet<>();
        if (CollUtil.isNotEmpty(boxMarkNoMatchList)) {
            productIdSet.addAll(boxMarkNoMatchList.values().stream().flatMap(List::stream).map(OrderBoxProductDo::getProductId).collect(Collectors.toSet()));
        }
        if (CollUtil.isNotEmpty(boxTypeNoMatchList)) {
            productIdSet.addAll(boxTypeNoMatchList.values().stream().flatMap(List::stream).map(OrderBoxProductDo::getProductId).collect(Collectors.toSet()));
        }
        Map<Long, ProductDo> productIdMatchDo = productService.lambdaQuery()
                .in(ProductDo::getId, productIdSet)
                .list().stream().collect(Collectors.toMap(ProductDo::getId, val -> val));
        orderInputService.proxyWarehousePushToJdy(event.getInputDo(), event.getBoxList(), boxMarkNoMatchList, boxTypeNoMatchList, productIdMatchDo);
    }

    /**
     * 出库单保存后事务提交后执行事件添加计费
     *
     * @param event 事件实体
     */
    @Async("threadPoolExecutor")
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void outboundAddCostEvent(OutboundAddCostEvent event) {
        if (Objects.isNull(event)) {
            return;
        }
        rabbitTemplate.convertAndSend(RabbitQueueConstant.Outbound_Add_Cost, JSONUtil.toJsonStr(event));
    }

    /**
     * 出库单auto send后状态修改
     *
     * @param event
     */
    @Async("threadPoolExecutor")
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void outboundAutoSendStatusEvent(OutboundAutoSendStatusEvent event) {
//        log.error("获取单号自动发货，修改状态开始");
        if (Objects.isNull(event)) {
            return;
        }
        rabbitTemplate.convertAndSend(RabbitQueueConstant.Outbound_Auto_Send_Log, JSONUtil.toJsonStr(event));
    }

    /**
     * 出库单发货后事务提交后后置操作
     *
     * @param event 事件实体
     */
    @Async("threadPoolExecutor")
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void outboundPostOperationEvent(OutboundPostOperationEvent event) {
        if (Objects.isNull(event)) {
            return;
        }
        rabbitTemplate.convertAndSend(RabbitQueueConstant.Outbound_Post_Operation, JSONUtil.toJsonStr(event));
    }

    /**
     * 调拨保存后事务提交后执行事件添加计费
     *
     * @param event 事件实体
     */
    @Async("threadPoolExecutor")
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void allocateAddCostEvent(AllocateAddCostEvent event) {
        quotationSchemeService.costAddOut(allocatePlanService.buildOutboundCostReq(event.getPlanDo(), event.getStatus()));
    }

    /**
     * 订单分包后处理出库单包裹信息
     *
     * @param event 事件实体
     */
    @Async("threadPoolExecutor")
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void orderSubcontractEvent(OrderSubcontractEvent event) {
        outboundService.dealPackageDetail(event);
    }
}